﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;

namespace OsmProcessing
{
    public class OsmFiltering
    {
        public void ExtractBikeRoutesInRegion(String osmFilePath, String osmOutputFilePath, Coordinate leftCorner, Coordinate rightCorner)
        {
            // Read a document
            XmlTextReader textReader = new XmlTextReader(osmFilePath);
            //XmlTextReader textReader = new XmlTextReader(@"f:\data\maps\osm\testing.osm");

            XmlTextWriter writer = new XmlTextWriter(osmOutputFilePath, Encoding.ASCII);
            writer.WriteStartElement("ways");
            // Read until end of file

            Dictionary<int, Coordinate> nodes = new Dictionary<int, Coordinate>();
            bool wayStarted = false;
            List<int> nodesInWay = null;

            while (textReader.Read())
            {
                XmlNodeType nType = textReader.NodeType;

                if (textReader.Name == "node" && textReader.AttributeCount >= 3)
                {
                    int id = Convert.ToInt32(textReader.GetAttribute(0));
                    double lat = Convert.ToDouble(textReader.GetAttribute(1));
                    double lng = Convert.ToDouble(textReader.GetAttribute(2));

                    //compare if the node is between selected rectangle
                    if (lat <= leftCorner.Latitude && lat >= rightCorner.Latitude
                        && lng <= rightCorner.Longitude && lng >= leftCorner.Longitude)
                    {
                        nodes.Add(id, new Coordinate(lat, lng));
                    }
                }



                if (textReader.Name == "way")
                {
                    if (!wayStarted)
                    {
                        wayStarted = true;
                        nodesInWay = new List<int>();
                    }
                    else
                    {
                        wayStarted = false;
                    }

                }

                if (textReader.Name == "nd")
                {
                    if (wayStarted)
                    {
                        nodesInWay.Add(Convert.ToInt32(textReader.GetAttribute(0)));
                    }
                }

                if (textReader.Name == "tag")
                {
                    if (wayStarted)
                    {
                        if (textReader.GetAttribute(0) == "cycleway" || textReader.GetAttribute(1) == "cycleway")
                        {

                            List<Coordinate> route = new List<Coordinate>();
                            
                            MemoryStream routeStream = new MemoryStream();
                            
                            XmlTextWriter routeWriter = new XmlTextWriter(routeStream, Encoding.ASCII);
                            routeWriter.WriteStartElement("way");
                            bool nodesFound = true;
                            foreach (var node in nodesInWay)
                            {
                                if (!nodes.ContainsKey(node))
                                {
                                    nodesFound = false;
                                    break;
                                }
                                route.Add(nodes[node]);
                                routeWriter.WriteStartElement("nd");
                                routeWriter.WriteAttributeString("lat", nodes[node].Latitude.ToString());
                                routeWriter.WriteAttributeString("lng", nodes[node].Longitude.ToString());
                                routeWriter.WriteEndElement();
                                
                            }
                            routeWriter.WriteEndElement();

                            if (nodesFound)
                            {
                                routeWriter.Flush();
                                routeStream.Position = 0;
                                var sr = new StreamReader(routeStream);
                                
                                var rarRouteXML = sr.ReadToEnd();
                                writer.WriteRaw(rarRouteXML);
                            }
                            
                            routeWriter.Close();
                            routeStream.Dispose();
                            
                        }
                    }
                }
            }
            writer.WriteEndElement();
            writer.Close();
            //XDocument xdoc = new XDocument(
            //    new XDeclaration("1.0", "utf-8", "yes"),
            //    new XComment("List of bike routes"), 
            //    new XElement("ways",
            //            from r in listOfRoutes
            //            select new XElement("way",
            //                from p in r
            //                select new XElement("point",
            //                    new XAttribute("lat", p.Latitude),
            //                    new XAttribute("lng", p.Longitude)
            //                )
            //            )
            //        )
            //    );
            //xdoc.Save(@"f:\data\maps\osm\output.bic");   
        }
    }
}
